/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.mzk.kramerius.rukopisyimport.cli;

import cz.mzk.kramerius.commons.CommandLineInterface;
import cz.mzk.kramerius.commons.PropertyLoader;
import cz.mzk.kramerius.rukopisyimport.ManuscriptCollection;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Martin Rehanek (rehan@mzk.cz)
 */
public class Main {

    private static final DefinedOptions DEFINED_OPTIONS = new DefinedOptions();
    //private static final Logger logger = Logger.getLogger(Main.class.getName());

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        String[] testArgs = new String[]{
            //"-p", "/home/rehan/rukopisy/project.properties",
            //"-p", "/home/rehan/rukopisy/chorinsti.properties",
            "-p", "/home/rehan/rukopisy/mk.properties",
            //"-p", "/home/rehan/rukopisy/chorinsti.properties",
            //  "-a", "updateMarc",
            "-a", "createFoxmls",
            //            //"-uuid", "7977d7ae-5465-4827-aa0e-a73dc94e58d8",
            //            //"-uuid", "test123",
            //"--ingest",
            //"--index",
            "--create-internal-parts",
            //            //"-a", "updateMarc",
            //            //"-s", "RKP-0755.199"
            //            "-s", "RKP2-0047.948,2"
            "-s", "Mk-0000.009",
            "-m", "manuscript",
            "-ii"
        //"-sf", "/home/rehan/rukopisy/moll-RKP2.sig"
        };
        //args = testArgs;
        try {
            CommandLineInterface cli = new CommandLineInterface(args, DEFINED_OPTIONS);
            Properties properties = loadProperties(cli.getStringValueOrNull(DEFINED_OPTIONS.PROPERTIES_FILE));
            List<Action> actions = determineActions(cli, properties);
            ActionResult previousActionResult = new ActionResult(true, null);
            for (Action action : actions) {
                if (previousActionResult.wasSuccessfull()) {
                    previousActionResult = action.run(previousActionResult);
                } else {
                    return;
                }
            }
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private static List<Action> determineActions(CommandLineInterface cli, Properties properties) throws Exception {
        String action = cli.getStringValueOrNull(DEFINED_OPTIONS.ACTION);
        if ("analyze".equals(action)) {
            ManuscriptCollection collection = loadCollection(properties);
            boolean detailedPrint = cli.getBooleanValue(DEFINED_OPTIONS.DETAILED_PRINT);
            List<Action> result = new ArrayList<Action>();
            result.add(new AnalyzeTeiDirAction(collection, properties, detailedPrint));
            return result;
        } else if ("updateMarc".equals(action)) {
            ManuscriptCollection collection = loadCollection(properties);
            System.out.println("collection:" + collection);
            List<Action> result = new ArrayList<Action>();
            result.add(new UpdateMarcRecordsForDigitizedTeisAction(collection, properties));
            return result;
        } else if ("createFoxmls".equals(action)) {
            ManuscriptCollection collection = loadCollection(properties);
            boolean inImageServer = cli.getBooleanValue(DEFINED_OPTIONS.MANUSCRIPTS_IN_IMAGE_SERVER);
            boolean createInternalParts = cli.getBooleanValue(DEFINED_OPTIONS.CREATE_INTERNAL_PARTS);
            boolean ingest = cli.getBooleanValue(DEFINED_OPTIONS.INGEST_FOXMLS);
            boolean index = cli.getBooleanValue(DEFINED_OPTIONS.INDEX_MANUSCRIPT);
            String uuid = cli.getStringValueOrNull(DEFINED_OPTIONS.UUID);
            String modelName = cli.getStringValueOrNull(DEFINED_OPTIONS.MODEL);
            //System.err.println("create internal parts: " + createInternalParts);
            List<String> signatures = loadSignatures(cli);
            if (signatures.size() == 1) {
                checkUuid(uuid);
                List<Action> result = new ArrayList<Action>();
                addActionsToList(result, signatures.get(0), uuid, collection, properties, inImageServer, ingest, index, createInternalParts, modelName);
                return result;
            } else {
                if (uuid != null) {
                    throw new Exception("option uuid cannot be used when multiple signatures are processed");
                }
                List<Action> result = new ArrayList<Action>();
                for (String signature : signatures) {
                    addActionsToList(result, signature, null, collection, properties, inImageServer, ingest, index, createInternalParts, modelName);
                }
                return result;
            }
        } else {
            throw new Exception("no such action '" + action + "'");
        }
    }

    private static void addActionsToList(List<Action> result, String signature, String uuid, ManuscriptCollection collection, Properties properties, boolean inImageServer, boolean ingest, boolean index, boolean createInternalParts, String modelName) {
        result.add(new CreateFoxmlFilesAction(collection, signature, uuid, properties, inImageServer, createInternalParts, modelName));
        if (ingest) {
            result.add(new ImportFoxmlFilesAction(collection, signature, properties));
            if (index) {
                result.add(new IndexManuscriptAction(properties));
            }
        }
    }

    private static List<String> loadSignatures(CommandLineInterface cli) {
        String signature = cli.getStringValueOrNull(DEFINED_OPTIONS.SIGNATURE);
        if (signature != null) {
            List<String> result = new ArrayList<String>();
            result.add(signature);
            return result;
        } else {
            String signaturesFile = cli.getStringValueOrNull(DEFINED_OPTIONS.SIGNATURE_FILE);
            if (signaturesFile == null) {
                System.err.println("not --signature nor --signatures-file option present");
                return Collections.<String>emptyList();
            } else {
                return signaturesFromFile(signaturesFile);
            }
        }
    }

    private static Properties loadProperties(String filename) throws IOException {
        Properties properties = new Properties();
        properties.load(new FileInputStream(filename));
        return properties;
    }

    private static ManuscriptCollection loadCollection(Properties properties) {
        PropertyLoader loader = new PropertyLoader(properties);
        String name = loader.loadString(PropertyNames.COLLECTION_NAME);
        String description = loader.loadString(PropertyNames.COLLECTION_DESC);
        File dir = loader.loadDir(PropertyNames.COLLECTION_DIR, true, true, false);
        return new ManuscriptCollection(dir, name, description);
    }

    private static List<String> signaturesFromFile(String filename) {
        try {
            List<String> result = new ArrayList<String>();
            File file = new File(filename);
            LineNumberReader reader = new LineNumberReader(new FileReader(file));
            String signatura;
            while (true) {
                signatura = reader.readLine();
                if (signatura != null && !"".equals(signatura)) {
                    result.add(signatura);
                } else {
                    break;
                }
            }
            reader.close();
            return result;
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            return Collections.<String>emptyList();
        }
    }

    private static void checkUuid(String uuid) throws Exception {
        if (uuid != null) {
            String template = "\\p{XDigit}{8}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{12}";
            if (!uuid.matches(template)) {
                throw new Exception("incorrect uuid '" + uuid + "'");
            }
        }
    }
}
